 
import { heapcache_roomposition } from "utils/decorate/decorate";
 
const NormalRoomfilter = (p:IFVector2)=>
        {
            if(p.x >=4 && p.x<=6 && p.y >=4 && p.y<=6 )
            {
                return false;
            }
            if(p.x==0 || p.y==0)
            {
                return false;
            }
            return true;
        }
  interface IPositionFilter
{
    (pos:RoomPosition):boolean
}
export class PositionHelper
{
    public static getObjectRef<T extends IDObject=IDObject>(obj:T|string):ObjectRef<T>
    {
        if(typeof obj == "string")
        {
            const obj2 = Game.getObjectById(obj as Id<AnyCreep|Structure>) as AnyCreep|Structure;
            if(obj2)
            {
                return PositionHelper.getObjectRef(obj2 as any) as ObjectRef<T>;
            }
            throw new Error(`${obj} 不在视野内或者不存在`)
        }
        else
        {
            return {x:obj.pos.x,y:obj.pos.y,roomName:obj.pos.roomName,id:obj.id  as any };
        }
        
    }

    // @heapcache_roomposition()
    public static Create(pos:IRoomPosition)
    {
        if(pos.x>49 || pos.x<0 || pos.y>49 || pos.y<0 || !pos.roomName)
        {
            //throw new Error(`position 错误${JSON.stringify(pos)}`);
            global.Log.Error(`position 错误${JSON.stringify(pos)} ${JSON.stringify(new Error().stack)}`);
        }
        // global.Log.Info(`new Position:[${JSON.stringify(pos)}]`);
        return new RoomPosition(pos.x,pos.y,pos.roomName);
    }
    public static roomCenter(room:string)
    {
        return this.Create({x:25,y:25,roomName:room})
    }
    public static seqId(roomName:string)
    {
        const pw = PositionHelper.worldPos(roomName);
        return pw.x+ pw.y*100
    }
    /**
     * 计算房间的周围一圈的房间名,默认范围为1，过滤为有控制器的房间
     * @param roomName 
     * @param range 
     * @param filter 
     * @returns 
     */
    public static calNeighborRoom(roomName:string,range=1,filter:(p:IFVector2)=>boolean=NormalRoomfilter)
    {
        const room = this.worldPos(roomName);
        const rooms:string[]=[];
        for(let i=-range;i<=range;i++)
        {
            for(let j=-range;j<=range;j++)
            {
                if(i==0 && j==0)
                {
                    continue;
                }
                let roomname= this.formatRoom({x:room.x+i,y:room.y+j});
                let pattern =/[EW](\d+)[SN](\d+)/;
                let [_,x,y] =roomname.match(pattern) as RegExpMatchArray;
                if(!filter || filter({x:parseInt(x),y: parseInt(y)}) )
                {
                    rooms.push( roomname);
                }
            }
        }
        return rooms
    }
    public static New(x:number,y:number,roomName:string)
    {
        if(x>49 ||y>49)
        {
            const thisworld = PositionHelper.ToWorld({x:x,y:y,roomName:roomName});
            return PositionHelper.WorldToRoom(thisworld);
        }
         return this.Create({x:x,y:y,roomName:roomName})
    }
    public static Add(pos:RoomPosition,x:number,y:number)
    {
        return this.New(pos.x+x,pos.y+y,pos.roomName);
    }
    public static format(pos:IRoomPosition)
    {
        return `${pos.roomName}_${pos.x}_${pos.y}`;
    }
    public static round(pos:IRoomPosition):IRoomPosition
    {
        return {x:Math.round(pos.x),y:Math.round(pos.x),roomName:pos.roomName}
    }
    public static inExit(pos:IRoomPosition)
    {
        return pos.x == 49 || pos.x == 0 || pos.y ==49 || pos.y == 0
    }
    
    public static roomParse(roomName:string ):{ [key: string]: number }
    {
        const isnum = (charval:string) =>{
            if(charval>='0' && charval<='9')
            {
                return true;
            }
            else
            {
                return false;
            }
        }
        let num;
        const room:{[key in string]:number}={};
         let curKey:string|undefined;
        for(let idx=0;idx<roomName.length;idx++)
        {
            // console.log('roomName[idx]= isnum'+isnum(roomName[idx]));
            if(isnum(roomName[idx]))
            {
                if(num)
                {
                    num=10*num+ parseInt(roomName[idx]);
                }
                else
                {
                    num=  parseInt(roomName[idx]);
                }
            }
            else
            {

                if(num !== undefined)
                {
                    if(curKey)
                    {
                        room[curKey]=num;
                    }

                }
                num=undefined;
                curKey = roomName[idx];
            }
        }
        if(curKey && num !==undefined)
        {
            room[curKey]=num;
        }
        return room;
    }
    public static  RoomPos(roomName:string): { [key: string]: number }
    {
        return this.roomParse(roomName);
    }
    public static  worldPos(roomName:string): {x:number,y:number }
    {
        const ret =  this.roomParse(roomName);
        let Nx = 0;
        let Ny = 0;
        for(let k in ret)
        {
            if (k == 'W')
            {
                Nx = -(ret[k] + 1);
            }else if (k == 'E')
            {
                Nx =ret[k];
            }
            if (k== 'N')
            {
                Ny = -(ret[k] + 1);
            }else if (k == 'S')
            {
                Ny =ret[k];
            }
        }
        return {x:Nx,y:Ny}
    }
    public static  Distance_Room(roomNameA:string,roomNameB:string): number
    {
        const pos1 = this.RoomPos(roomNameA);
        const pos2 = this.RoomPos(roomNameB);
        const xOffset = Math.abs(pos1.x - pos2.x);
        const yOffset = Math.abs(pos1.y - pos2.y);
        return xOffset > yOffset ? xOffset : yOffset;
    }
    public static ToWorld(pos:IRoomPosition): { [key: string]: number }
    {
        if(!pos || !pos.roomName)
        {
            throw new Error(`pos 错误${ JSON.stringify(pos)}`);
        }
       let pattern =/[A-Z]+[0-9]+/g;
       let res =pos.roomName.match(pattern) as RegExpMatchArray;
       let Nx = 0;
       let Ny = 0;
       if(res[0] && res[1]  )
       {
           if (res[0][0] == 'W')
           {
               Nx = parseInt(res[0].substring(1));
               Nx = -(Nx + 1);
           }else if (res[0][0] == 'E')
           {
           Nx = parseInt(res[0].substring(1));
           }
           if (res[1][0] == 'N')
           {
           Ny = parseInt(res[1].substring(1));
           Ny = -(Ny + 1);
           }else if (res[1][0] == 'S')
           {
           Ny = parseInt(res[1].substring(1));
           }
       }
       else
       {
           Memory.Debug[`${Game.time} 房间名转换错误:`] = pos.roomName;
       }

       return { x: Nx*50+pos.x, y: Ny*50+pos.y };
    }
    private static formatRoom(worldPos:{ [key: string]: number })
    {
        const xVal = worldPos.x;
        const yVal = worldPos.y;
        let roomname='';
        {
            const x1 = xVal;
            if(x1<0)
            {
                roomname+=`W${-x1-1}`;
            }
            else
            {
                roomname+=`E${x1}`;
            }
        }
        {
            const x1 = yVal;
            if(x1<0)
            {
                roomname+=`N${-x1-1}`;
            }
            else
            {
                roomname+=`S${x1}`;
            }
        }
        return roomname;
    }
    public static getCenterRoom(roomName:string)
    {
        const v = this.roomParse(roomName);
        for(let k in v)
        {
            v[k] = Math.floor(v[k]/10)*10+5;
        }
        const keys=["W","E","N","S"];
        let retroomName="";
        for(const e of keys)
        {
            if(v[e] === undefined)
            {
                continue;
            }
            retroomName+=`${e}${v[e]}`
        }
        return retroomName;
    }
    public static WorldToRoom(worldPos:{ [key: string]: number }):RoomPosition
   {

      const xVal = worldPos.x;
      const yVal = worldPos.y;
      let roomname='';
        {
            const x1 = Math.floor( xVal/50);
            if(x1<0)
            {
                roomname+=`W${-x1-1}`;
            }
            else
            {
                roomname+=`E${x1}`;
            }
        }
        {
            const x1 = Math.floor( yVal/50);
            if(x1<0)
            {
                roomname+=`N${-x1-1}`;
            }
            else
            {
                roomname+=`S${x1}`;
            }
        }
      let rvalx= xVal%50;
      rvalx = rvalx>=0?rvalx:rvalx+50;
      let rvaly= yVal%50;
      rvaly = rvaly>=0?rvaly:rvaly+50;
      // console.log(`${roomname}:${rvalx}-${rvaly}`);
      return this.Create({x:rvalx,y:rvaly,roomName:roomname});
   }
    public static isInExit(pos:IRoomPosition)
    {
        if(pos.x== 0 || pos.x==49 ||pos.y== 0 || pos.y==49 )
        {
            return true;
        }
        return false;
    }
    public static lookFor<T extends keyof AllLookAtTypes>(type: T,pos:IRoomPosition): Array<AllLookAtTypes[T]>
    {
        if(Game.rooms[pos.roomName])
        {
            return Game.rooms[pos.roomName].lookForAt(type,pos.x,pos.y);
        }
        return []
    }
    /**
     * 获取出口坐标在另一个房间的坐标
     * @param pos
     * @returns
     */
    public static getNabRoomposition(pos:IRoomPosition,range=1)
    {
        const world_pos =this.ToWorld(pos);
        if(pos.x<range)
        {
            world_pos.x = world_pos.x-range;
        }
        else if(pos.x>(50-range))
        {
            world_pos.x = world_pos.x+range;
        }
        else if(pos.y<range)
        {
            world_pos.y = world_pos.y-range;
        }
        else if(pos.y>(50-range))
        {
            world_pos.y = world_pos.y+range;
        }
        else
        {
            return undefined;
        }
        return this.WorldToRoom(world_pos);
    }
    public static addPosition(pos:IRoomPosition,offset:IFVector2)
    {
        let targetX = pos.x+offset.x
        let targetY =pos.y+offset.y

        // 如果要移动到另一个房间的话就转换到世界坐标
        if (targetX < 0 || targetY > 49 || targetX > 49 || targetY < 0)
        {

           let worldpos = this.ToWorld(pos);

           worldpos.x += offset.x;
           worldpos.y += offset.y;
           return  this.WorldToRoom(worldpos);
        }
        else
        {
            return this.Create({x:targetX, y:targetY, roomName:pos.roomName})
        }
    }
    /**
     * 切比雪夫距离 
     * @param posa
     * @param pos
     * @returns
     */
    public static  Distance(posa:IRoomPosition,pos:IRoomPosition|undefined):number
    {
        if ( pos== undefined || posa.roomName != pos.roomName )
        {
            if (pos)
            {
                let thisworld =  this.ToWorld(posa);
                let otherpos =  this.ToWorld(pos);
                let nX =  Math.abs(thisworld.x-otherpos.x) ;
                let nY = Math.abs(thisworld.y - otherpos.y);
                return nX>nY?nX:nY;
            }

            return 50;
        }
        let nX =  Math.abs(posa.x-pos.x) ;
        let nY =  Math.abs(posa.y-pos.y);
        return nX>nY?nX:nY;
    }


    public static isEqual(posa:IRoomPosition,posb:IRoomPosition)
    {
        return   posa.x === posb.x  &&  posa.y === posb.y && posa.roomName === posb.roomName ;
    }

    public static getDirection(from:IFVector2,to:IFVector2):DirectionConstant
    {
        let x_offset = to.x-from.x;
        if(x_offset!=0)
        {
            x_offset = x_offset/Math.abs(x_offset);
        }
        let y_offset = to.y-from.y;
        if(y_offset!=0)
        {
            y_offset = y_offset/Math.abs(y_offset);
        }

        switch(x_offset)
        {
            case -1:
                {
                    switch(y_offset)
                    {
                        case 1:
                            return BOTTOM_LEFT;
                        case 0:
                            return LEFT;
                        case -1:
                            return TOP_LEFT;
                    }
                }
                break;
            case 0:
                {
                    switch(y_offset)
                    {
                        case 1:
                            return BOTTOM;
                        case -1:
                            return TOP;
                        case 0:
                            return 0 as DirectionConstant;
                    }
                }
                break;
            case 1:
            {
                switch(y_offset)
                    {
                        case 1:
                            return BOTTOM_RIGHT;
                        case 0:
                            return RIGHT;
                        case -1:
                            return TOP_RIGHT;
                    }
            }
        }
        global.Log.Error(`两个坐标不是相邻关系 x:${x_offset} y:${y_offset} from:${JSON.stringify(from)} to:${JSON.stringify(to)}`);
        return 0 as DirectionConstant;
    }
 
    /**
     * 查找指定坐标的周围一圈空闲坐标,按照顺时针方向
     * @param pos 中心点
     * @param range 范围
     * @returns
     */
    public static findRingOfPosition(pos:IRoomPosition,range:number)
    {
        const terrain=  Game.rooms[pos.roomName].getTerrain();

        const offset = [ - range,   range];

        // 1.
        const pos_group:RoomPosition[][]=[]
        {

            let tmp_arr:RoomPosition[]=[];
            const func=(x:number,y:number)=>{

                if(x<0|| y<0||x>49||y>49||terrain.get(x,y) == TERRAIN_MASK_WALL)
                {
                    // 中断
                    // Memory.Debug[`中断 ${x}_${y}_${range}`]= JSON.stringify(tmp_arr);
                    if(tmp_arr.length>0)
                    {
                        pos_group.push(tmp_arr);

                        tmp_arr=new Array<RoomPosition>();

                    }

                }
                else
                {

                    //
                    tmp_arr.push(PositionHelper.Create({x:x,y:y,roomName:pos.roomName}));

                }
            }
            // x+ -y
            for(let n=offset[0];n<offset[1];n++)
            {
                let nx = pos.x+n;
                let ny =  pos.y-range;
                func(nx,ny);
            }
             // +x y+
            for(let n=offset[0];n<offset[1];n++)
            {
                let nx = pos.x+range;
                let ny =  pos.y+n;
                func(nx,ny);
            }
             // x- +y
            for(let n=offset[1];n>offset[0];n--)
            {
                let nx = pos.x+n;
                let ny =  pos.y+range;
                func(nx,ny);
            }
            // -x y-
            for(let n=offset[1];n>offset[0];n--)
            {
                let nx =  pos.x-range;
                let ny =  pos.y+n;
                func(nx,ny);
            }
            if(tmp_arr.length>0)
            {
                pos_group.push(tmp_arr);
            }
        }

        // 2.首位缝合

        if(pos_group.length>1)
        {
            const firstp = pos_group[0][0];
            const lastarr=pos_group[pos_group.length-1];
            const endp = lastarr[lastarr.length-1];
            if(PositionHelper.Distance(firstp,endp)<=1)
            {
                // 合并
                const firstarr=pos_group[0];
                pos_group.splice(0,1);
                pos_group[pos_group.length-1].push(...firstarr);
            }
        }
        return pos_group;
    }
/**
     * 查找指定坐标的周围一圈空闲坐标,按照顺时针方向
     * @param pos 中心点
     * @param range 范围
     * @returns
     */
 public static findRingOfValidPosition(pos:IRoomPosition,range:number,filter?:IPositionFilter)
 {
    if(! Game.rooms[pos.roomName])
    {
        throw new Error(`${pos.roomName} 没有视野`);
    }
     const terrain=  Game.rooms[pos.roomName].getTerrain();

     const offset = [ - range,   range];

     // 1.
     const pos_group:RoomPosition[][]=[]
     {

         let tmp_arr:RoomPosition[]=[];
         const func=(x:number,y:number)=>{

             if(x<0|| y<0||x>49||y>49||terrain.get(x,y) == TERRAIN_MASK_WALL)
             {
                 // 中断
                 // Memory.Debug[`中断 ${x}_${y}_${range}`]= JSON.stringify(tmp_arr);
                 if(tmp_arr.length>0)
                 {
                     pos_group.push(tmp_arr);

                     tmp_arr=new Array<RoomPosition>();

                 }

             }
             else
             {

                 //
                 if(filter)
                 {
                    if(filter(PositionHelper.Create({x:x,y:y,roomName:pos.roomName})))
                    {
                        tmp_arr.push(PositionHelper.Create({x:x,y:y,roomName:pos.roomName}));
                    }
                 }
                 else
                 {
                    tmp_arr.push(PositionHelper.Create({x:x,y:y,roomName:pos.roomName}));
                 }


             }
         }
         // x+ -y
         for(let n=offset[0];n<offset[1];n++)
         {
             let nx = pos.x+n;
             let ny =  pos.y-range;
             func(nx,ny);
         }
          // +x y+
         for(let n=offset[0];n<offset[1];n++)
         {
             let nx = pos.x+range;
             let ny =  pos.y+n;
             func(nx,ny);
         }
          // x- +y
         for(let n=offset[1];n>offset[0];n--)
         {
             let nx = pos.x+n;
             let ny =  pos.y+range;
             func(nx,ny);
         }
         // -x y-
         for(let n=offset[1];n>offset[0];n--)
         {
             let nx =  pos.x-range;
             let ny =  pos.y+n;
             func(nx,ny);
         }
         if(tmp_arr.length>0)
         {
             pos_group.push(tmp_arr);
         }
     }

     // 2.首位缝合

     if(pos_group.length>1)
     {
         const firstp = pos_group[0][0];
         const lastarr=pos_group[pos_group.length-1];
         const endp = lastarr[lastarr.length-1];
         if(PositionHelper.Distance(firstp,endp)<=1)
         {
             // 合并
             const firstarr=pos_group[0];
             pos_group.splice(0,1);
             pos_group[pos_group.length-1].push(...firstarr);
         }
     }
     return _.flatten(pos_group);
 }

 /**
     * 查找指定坐标的周围一圈空闲坐标,按照顺时针方向
     * @param pos 中心点
     * @param range 范围
     * @returns
     */
    public static findValidPosition(pos:IRoomPosition,range:number,filter?:IPositionFilter)
    {
        if(! Game.rooms[pos.roomName])
        {
            throw new Error(`${pos.roomName} 没有视野`);
        }
        const terrain=  Game.rooms[pos.roomName].getTerrain();

        const offset = [ - range,   range];

        const xs = [pos.x - range,  pos.x + range]
        const ys = [pos.y - range,  pos.y + range]
        let tmp_arr:RoomPosition[]=[];
        const func=(x:number,y:number)=>{

            if(x<0|| y<0||x>49||y>49||terrain.get(x,y) == TERRAIN_MASK_WALL)
            {
                // 不能站

            }
            else
            {

                //
                if(filter)
                {
                    if(filter(PositionHelper.Create({x:x,y:y,roomName:pos.roomName})))
                    {
                        tmp_arr.push(PositionHelper.Create({x:x,y:y,roomName:pos.roomName}));
                    }
                }
                else
                {
                    tmp_arr.push(PositionHelper.Create({x:x,y:y,roomName:pos.roomName}));
                }
            }
        }
        for(let nx = xs[0];nx<=xs[1];nx++)
        {
            for(let ny = ys[0];ny<=ys[1];ny++)
            {
                func(nx,ny);
            }
        }
        return tmp_arr;
    }
    static getExitCenter(key:ExitKey,roomName:string)
    {
        switch(key)
        {
            case "1":
                // top
                return this.Create({x:25,y:1,roomName:roomName});

            case "3":
                // right
                return this.Create({x:48,y:25,roomName:roomName});
            case "5":
                // bottom
                return this.Create({x:25,y:48,roomName:roomName});
            case "7":
                // left
                return this.Create({x:1,y:25,roomName:roomName});
        }
    }

    static to1D(pos:IFVector2)
    {
        return pos.x+pos.y*50;
    }

    static lookForAtArea<T extends keyof AllLookAtTypes>(type:T,pos:IRoomPosition[],range:number)
    {
        if(pos.length==0)
        {
            throw new Error(`pos length 为0`);
        }
        if(!Game.rooms[pos[0].roomName])
        {
            throw new Error(`房间[${pos[0].roomName}]不在视野内`);
        }
        const min_x = _.min(pos,e=>e.x).x;
        const min_y = _.min(pos,e=>e.y).y;
        const max_x = _.max(pos,e=>e.x).x;
        const max_y = _.max(pos,e=>e.y).y;
        const top = Math.max(0,min_y-range);
        const left = Math.max(0,min_x-range);
        const right = Math.min(49,max_x+range);
        const bottom = Math.min(49,max_y+range);

        const ret = Game.rooms[pos[0].roomName].lookForAtArea(type,top,left,bottom,right,true);
        return ret
    }
    /**
     *
     * @param curpos
     * @returns 返回一个边界坐标与之相邻的房间
     */
    static getTargetNabRoom(curpos:IRoomPosition)
    {
        const nabrooms = Game.map.describeExits(curpos.roomName);
        if(curpos.x==0)
        {
            return nabrooms["7"];
        }
        else  if(curpos.x==49)
        {
            return nabrooms["3"];
        }
        else  if(curpos.y==0)
        {
            return nabrooms["1"];
        }
        else  if(curpos.y==49)
        {
            return nabrooms["5"];
        }
        return undefined
    }

    static isNabRoom(rooma:string,roomb:string)
    {
        const nabrooms = Game.map.describeExits(rooma);
        for(const key in nabrooms)
        {
            if(nabrooms[key  as ExitKey] == roomb)
            {
                return true;
            }
        }
        return false;
    }


    private static standardizePosstring(pos:string):string|null
    {
        return `${pos}/${Game.shard.name}`
    }
    public static  standardizePos(pos: IRoomPosition): string {
        return `${pos.x}/${pos.y}/${pos.roomName}`
    }

    public static getDistance (p1:IFVector2,p2:IFVector2) 
    {
        const dis_x = Math.abs(p1.x -p2.x);
        const dis_y = Math.abs(p1.y -p2.y);
        // 存在爬的话距离要变大

        return Math.max(dis_x,dis_y);
    }

     /**
     * 获取该位置周围的开采位空位
     */
    public static getFreeSpace(p:IRoomPosition,range:number=1,includeself:boolean=false,excludestructure=false): RoomPosition[] 
        {

        const terrain = new Room.Terrain(p.roomName);
        const result: RoomPosition[] = []

        const xs = [p.x - range,  p.x + range]
        const ys = [p.y - range,  p.y + range]

        if(includeself)
        {
            for(let nx = xs[0];nx<=xs[1];nx++)
            {
                for(let ny = ys[0];ny<=ys[1];ny++)
                {

                    if (  (nx<50 && nx>=0) && (ny<50 && ny>=0))
                    {
                        if (terrain.get(nx, ny) != TERRAIN_MASK_WALL) result.push(PositionHelper.New(nx, ny, p.roomName))
                    }
                }
            }
        }
        else
        {
            for(let nx = xs[0];nx<=xs[1];nx++)
            {
                for(let ny = ys[0];ny<=ys[1];ny++)
                {
                    if ((nx != p.x || ny != p.y)&& (nx<50 && nx>=0) && (ny<50 && ny>=0))
                    {
                        if (terrain.get(nx, ny) != TERRAIN_MASK_WALL) result.push(PositionHelper.New(nx, ny, p.roomName))
                    }
                }
            }
        }
        if(excludestructure)
        {
            return this.FilterBlockPos(result);
        }
        return result
    }

    
    private  static FilterBlockPos(poss:RoomPosition[])
    {
        return _.filter(poss,item=>{
            if(!Game.rooms[item.roomName])
            {
                // 找不到room则认为没有建筑则是可以的
                return true;
            }
        const findres =  PositionHelper.lookFor(LOOK_STRUCTURES,item).find(struct=>struct.structureType != STRUCTURE_ROAD && struct.structureType != STRUCTURE_CONTAINER)
        if(findres)
        {
            return false;
        }
        const siteres =  PositionHelper.lookFor(LOOK_CONSTRUCTION_SITES,item).find(struct=>struct.structureType != STRUCTURE_ROAD && struct.structureType != STRUCTURE_CONTAINER)
        if(siteres)
        {
            return false;
        }
        return true;
        })
    }


     /**
    * 获取出口坐标
    * @param roomName
    * @param exit 出口方向
    * @returns 出口坐标
    */
    public static getExitPositions(roomName:string,exit:ExitKey)
    {

        const terrain = Game.map.getRoomTerrain(roomName);
        const allexits:IRoomPosition[][]=[];
        let exits:IRoomPosition[]=[];
        switch(exit)
        {
            case "1":
            {
                // top
                for(let i=0;i<50;i++)
                {
                    if(terrain.get(i,0)!=TERRAIN_MASK_WALL)
                    {
                        exits.push({x:i,y:0,roomName:roomName})
                    }
                    else
                    {
                        if(exits.length>0)
                        {
                            allexits.push(exits);
                            exits=[]
                        }
                    }
                }
                break;
            };
            case "3":
            {
                // right
                for(let i=0;i<50;i++)
                {
                    if(terrain.get(49,i)!=TERRAIN_MASK_WALL)
                    {
                        exits.push({x:49,y:i,roomName:roomName})
                    }else
                    {
                        if(exits.length>0)
                        {
                            allexits.push(exits);
                            exits=[]
                        }
                    }
                }
                break;
            };
            case "5":
            {
                // btm
                for(let i=0;i<50;i++)
                {
                    if(terrain.get(i,49)!=TERRAIN_MASK_WALL)
                    {
                        exits.push({x:i,y:49,roomName:roomName})
                    }else
                    {
                        if(exits.length>0)
                        {
                            allexits.push(exits);
                            exits=[]
                        }
                    }
                }
                break;
            };
            case "7":
            {
                // left
                for(let i=0;i<50;i++)
                {
                    if(terrain.get(0,i)!=TERRAIN_MASK_WALL)
                    {
                        exits.push({x:0,y:i,roomName:roomName})
                    }else
                    {
                        if(exits.length>0)
                        {
                            allexits.push(exits);
                            exits=[]
                        }
                    }
                }
                break;
            };

        }
        return allexits;
    }

    public static getExitPositionsBetweenRooms(room_a:string,room_b:string)
    {
        const exits = Game.map.describeExits(room_a);
        if(exits)
        {
            // 1.出口判断
            for(const key in exits)
            {
                if(exits[key as ExitKey] == room_b)
                {
                    const allexit_pos = this.getExitPositions(room_a,key as ExitKey);
                    // 数组的首尾必然是挨着墙的
                    if(allexit_pos.length>0)
                    {
                       
                        return _.flatten( allexit_pos.map(e=>{
                            if(e.length>2)
                            {
                                return [e[0],e[e.length-1]]
                            }
                            return e
                        }))
                    }
                }
            }
        }
        return false
    }
    
}
